package com.example.onlinemusic.controller;

import com.example.onlinemusic.mapper.LoveMusicMapper;
import com.example.onlinemusic.mapper.MusicMapper;
import com.example.onlinemusic.model.Contant;
import com.example.onlinemusic.model.Music;
import com.example.onlinemusic.model.User;
import com.example.onlinemusic.tools.ResponseBodyMessage;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;


/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: hold on
 * Date: 2022-07-27
 * Time: 15:40
 */
@RestController
@RequestMapping("/music")
public class MusicController {

//    //文件上传服务器后的路径地址!
//    private String SAVE_PATH = "D:/uploadmusicfile/";

    //我们可以将该路径信息设置到配置文件中!
    @Value("${music.path.save}")
    private String SAVE_PATH;

    //上传音乐到数据库的url前缀
    @Value("${music.url}")
    private String URL_PRE;

    @Resource  //属性注入
    private MusicMapper musicMapper;
    @Resource
    private LoveMusicMapper loveMusicMapper;

    //这里的上传需要将音乐上传到服务器,还有就是需要将音乐信息上传到数据库!
    @RequestMapping("/upload")                     //当我们没有传歌手信息时,就默认为未知歌手
    public ResponseBodyMessage<Boolean> UploadMusic(@RequestParam(defaultValue = "未知歌手") String singer,
                                                     @RequestParam(value = "filename") MultipartFile file,
                                                     HttpServletRequest request,
                                                     HttpServletResponse resp) {

        //1.上传音乐前验证登入状态,如果未登入就不创建会话
        //如果用户已登入,则允许上传音乐!
        HttpSession session = request.getSession(false);
        if (session == null || session.getAttribute(Contant.USERINFO_SESSION_KEY) == null) {
            //未登入状态!
            System.out.println("未登入");
            return new ResponseBodyMessage<>(-1, "未登录,请登录后上传!", false);
        }
        //2.登入状态,可以将歌曲上传到服务器!
        //1.先验证是否为音乐文件!
        boolean flg = false;
        try {
            //获取到后128位含有标志字节的字符串
            String str = new String(file.getBytes());
            System.out.println("str:" + str);
            //精准定位到TAG标志,其实就是倒数第128个字节就是TAG标志!
            String flgTAG = str.substring(str.length()-128);
            System.out.println("str:" + flgTAG);
            if (flgTAG.contains("TAG")) {
                //含有标志位,为音乐文件!
                flg = true;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (!flg) {//不是音乐文件
            return new ResponseBodyMessage<>(-1, "上传失败,文件有误,并非mp3音乐文件", false);
        }
            //获取到音乐文件名  xxx.mp4
            String musicname = file.getOriginalFilename();
            System.out.println("musicfileAndtype:" + musicname);

            //上传歌曲前验证歌曲是否已经存在!
            String title = musicname.substring(0, musicname.lastIndexOf(".mp3"));
            //获取到当前用户id
            User user = (User) session.getAttribute(Contant.USERINFO_SESSION_KEY);
            int user_id = user.getId();
            Music music = musicMapper.getMusicByUidAndMusicInfo(title, singer, user_id);
            if (music != null) { //说明该歌曲重复上传
                System.out.println(title + "已存在");
                return new ResponseBodyMessage<>(-1, "重复上传,歌曲已存在", false);
            }
            //歌曲未上传
            //上传文件在服务器下保存的路径!
            String path = SAVE_PATH + musicname;
            //创建文件对象
            File dest = new File(path);
            //该文件目录在磁盘中不存在,就创建该目录
            if (!dest.exists()) {
                dest.mkdir();
                System.out.println("mkdir" + dest);
            }
            //将音乐文件上传到该目录下!
            try {
                file.transferTo(dest);
                System.out.println(dest);
            } catch (IOException e) {
                e.printStackTrace();
                //上传失败
                return new ResponseBodyMessage<>(-1, "服务器上传失败", false);
            }
            //服务器上传成功,我们就需要对数据库进行上传信息!

            //1.数据准备
            //1).title 通过文件名截取到歌名,验证上传重复上传时已获取title
            //String title = musicname.substring(0,musicname.lastIndexOf(".mp3"));
            //2).singer 直接获取用户上传的 singer
            //3).time
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            String time = simpleDateFormat.format(new Date());
            //4).url 可以通过拼接! eg: music/get?path=隆里电丝
            String url = URL_PRE + title;
            //5).user_id 通过当前session获取,验证重复上传时已获取
//        User user = (User)session.getAttribute(Contant.USERINFO_SESSION_KEY);
//        int user_id = user.getId();
            int ret = musicMapper.upload(title, singer, time, url, user_id);
            if (ret != 1) {//上传失败!
                //我们数据库上传失败,那么就需要将服务器下的该音乐文件删除
                System.out.println("服务器上传成功,数据库上传失败,删除服务器下文件");
                dest.delete();
                return new ResponseBodyMessage<>(-1, "数据库上传失败", false);
            }
            //上传成功跳转到音乐列表
            try {
                resp.sendRedirect("/list.html");
            } catch (IOException e) {
                e.printStackTrace();
            }
            return new ResponseBodyMessage<>(0, "上传成功", true);
        }
    //实现支持多个文件上传就将MultipartFile改成数组即可!
    @RequestMapping("/uploads")
    public ResponseBodyMessage<Boolean> UploadMusics(@RequestParam(defaultValue = "未知歌手") String singer,
                                                    @RequestParam(value = "filename") MultipartFile[] files,
                                                    HttpServletRequest request){

        //1.上传音乐前验证登入状态,如果未登入就不创建会话
        //如果用户已登入,则允许上传音乐!
        HttpSession session = request.getSession(false);
        if(session==null||session.getAttribute(Contant.USERINFO_SESSION_KEY)==null){
            //未登入状态!
            System.out.println("未登入");
            return new ResponseBodyMessage<>(-1,"未登录,请登录后上传!",false);
        }
        //2.登入状态,可以将歌曲上传到服务器!

        //保存上传失败的歌曲信息
        StringBuilder uploadfailinfo = new StringBuilder();
        for (MultipartFile file:files) {

            //获取到音乐文件名  xxx.mp4
            String musicname = file.getOriginalFilename();
            System.out.println("musicfileAndtype:"+musicname);

            //上传歌曲前验证歌曲是否已经存在!
            String title = musicname.substring(0,musicname.lastIndexOf(".mp3"));
            //获取到当前用户id
            User user = (User)session.getAttribute(Contant.USERINFO_SESSION_KEY);
            int user_id = user.getId();
            Music music = musicMapper.getMusicByUidAndMusicInfo(title,singer,user_id);
            if(music!=null){ //说明该歌曲重复上传
                System.out.println(title+"已存在");
                //保存歌曲信息,用于返回前端用户!
                uploadfailinfo.append(title+",");
                //进行下一首歌曲上传
                continue;
            }
            //歌曲未上传
            //上传文件在服务器下保存的路径!
            String path = SAVE_PATH + musicname;
            //创建文件对象
            File dest = new File(path);
            //该文件目录在磁盘中不存在,就创建该目录
            if(!dest.exists()){
                dest.mkdir();
                System.out.println("mkdir"+dest);
            }
            //将音乐文件上传到该目录下!
            try {
                file.transferTo(dest);
                System.out.println(dest);
            } catch (IOException e) {
                e.printStackTrace();
                //上传失败
                return new ResponseBodyMessage<>(-1,"服务器上传失败",false);
            }
            //服务器上传成功,我们就需要对数据库进行上传信息!

            //1.数据准备
            //1).title 通过文件名截取到歌名,验证上传重复上传时已获取title
            //String title = musicname.substring(0,musicname.lastIndexOf(".mp3"));
            //2).singer 直接获取用户上传的 singer
            //3).time
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            String time = simpleDateFormat.format(new Date());
            //4).url 可以通过拼接! eg: music/get?path=隆里电丝
            String url = URL_PRE+title;
            //5).user_id 通过当前session获取,验证重复上传时已获取
//        User user = (User)session.getAttribute(Contant.USERINFO_SESSION_KEY);
//        int user_id = user.getId();
            int ret = musicMapper.upload(title,singer,time,url,user_id);
            if(ret!=1){//上传失败!
                //我们数据库上传失败,那么就需要将服务器下的该音乐文件删除
                System.out.println("服务器上传成功,数据库上传失败,删除服务器下文件");
                dest.delete();
                return new ResponseBodyMessage<>(-1,"数据库上传失败",false);
            }

        }
        if(uploadfailinfo.length()==0) {
            //说明全部歌曲上传成功!
            return new ResponseBodyMessage<>(0, "上传成功", true);
        }
        //部分歌曲上传失败
        return new ResponseBodyMessage<>(0,"歌曲:"+uploadfailinfo+"已存在,上传失败,"+"其他歌曲上传成功",true);

    }

    //播放音乐
    @RequestMapping("/get")
    public ResponseEntity<byte[]> get(String path){
        //我们要先获取到该音乐保存在服务器下的路径信息!
        try {
            byte[] fileByte = null;
            //获取到文件对象
            File file = new File(SAVE_PATH +File.separator+ path);
            //获取到该文件对象的路径信息
           Path filepath =  file.toPath();
            //读取文件中的所有字节
            fileByte = Files.readAllBytes(filepath);
            return ResponseEntity.ok(fileByte);
        }catch (IOException e){
            e.printStackTrace();
        }
        return ResponseEntity.badRequest().build();
    }


    //音乐文件验证
    @RequestMapping("/ismp3")
    public ResponseBodyMessage<String> ismp3(String path){
        String str = null;
        File file = null;
        byte [] fileByte = null;
        try {
             file= new File(SAVE_PATH+File.separator+path);
            //获取到这个文件的所有字节信息
            fileByte = Files.readAllBytes(file.toPath());
        } catch (IOException e) {
            e.printStackTrace();
        }
        //将字节数组转成字符串
        str = new String(fileByte);
        //获取到最后128个字节的字符串信息!
        str = str.substring(str.length()-128);

        if(str.contains("TAG")){//最后128字节,含有音乐文件标志
            return new ResponseBodyMessage<String>(0,"mp3文件",str);
        }
        //没有音乐文件标识
        return new ResponseBodyMessage<String>(-1,"非mp3文件",str);
    }

    //删除单个音乐
    @RequestMapping("/delete")
    public ResponseBodyMessage<Boolean> deleteMusic(@RequestParam Integer id){
        //1.首先找到该音乐信息
        Music music = musicMapper.getMusicById(id);
        if(music==null){//音乐不存在
            //未找到该音乐
            return new ResponseBodyMessage<>(-1,"需要删除的音乐不存在",false);
        }
        //2.进行音乐删除
        //2.1 删除服务器下的音乐文件
            //找到服务器下该音乐文件路径
            File file = new File(SAVE_PATH+File.separator+music.getTitle()+".mp3");
        System.out.println("musicPath:"+file.getPath());
            if(file==null){//服务器下不存在该文件
                return new ResponseBodyMessage<>(-1,"删除失败,服务器下未找到该文件信息",false);
            }
            //删除
            if(!file.delete()){
                //删除失败
                return new ResponseBodyMessage<>(-1,"服务器删除失败",false);
            }
        //2.2 删除数据库下的音乐信息
        //2.2.1删除music表中的音乐信息
       int ret = musicMapper.deleteById(id);
       if(ret!=1){//数据库删除失败
           return new ResponseBodyMessage<>(-1,"数据库信息删除失败",false);
       }
       //2.2.2删除lovemusic表中的音乐信息
       loveMusicMapper.deleteLoveMusicByMusicId(id);
       return new ResponseBodyMessage<>(0,"删除成功!",true);
    }

    //批量删除音乐
    @RequestMapping("/deleteAll")
    public ResponseBodyMessage<Boolean> deleteMusicAll(@RequestParam(value = "id[]") List<Integer> ids){
        String message = "";
        for (Integer id:ids) {
            //1.首先找到该音乐信息
            Music music = musicMapper.getMusicById(id);
            if(music==null){//音乐不存在
                //未找到该音乐
                //保存这个音乐id信息
                message += id+" ";
                continue;
                //return new ResponseBodyMessage<>(-1,"需要删除的音乐不存在",false);
            }
            //2.进行音乐删除
            //2.1 删除服务器下的音乐文件
            //找到服务器下该音乐文件路径
            File file = new File(SAVE_PATH+File.separator+music.getTitle()+".mp3");
            System.out.println("musicPath:"+file.getPath());
            if(file==null){//服务器下不存在该文件
                //保存这个id信息
                 message += id + "";
                 continue;
                //return new ResponseBodyMessage<>(-1,"删除失败,服务器下未找到该文件信息",false);
            }
            //删除
            if(!file.delete()){
                //删除失败
                message += id + "";
                continue;
                //return new ResponseBodyMessage<>(-1,"服务器删除失败",false);
            }
            //2.2 删除数据库下的音乐信息
            int ret = musicMapper.deleteById(id);
            if(ret!=1){//数据库删除失败
                message += id+" ";
                continue;
                //return new ResponseBodyMessage<>(-1,"数据库信息删除失败",false);
            }
            //取消该歌曲的所有收藏
            loveMusicMapper.deleteLoveMusicByMusicId(id);
        }
        if(message==""){
            return new ResponseBodyMessage<>(0,"删除成功!",true);
        }
        //部分删除失败
        return new ResponseBodyMessage<>(0,"id:" + message+" 删除失败!",true);
    }

    //模糊查询
    @RequestMapping("/findMusic")
    public ResponseBodyMessage<List<Music>> findMusic(@RequestParam(required =false) String musicName){
        List<Music> musicList = new LinkedList<>();
        if(musicName==null){
            //查询名称为空,查询所有音乐返回
            musicList = musicMapper.findMusic();
            return new ResponseBodyMessage<>(0,"查询成功!",musicList);
        }
        //进行模糊查询!
        musicList = musicMapper.findMusicByName(musicName);
         return new ResponseBodyMessage<>(0,"查询成功!",musicList);
    }
}
